﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OleDb;
using System.Data;

namespace PlateNumber {
    public static class VINGenerator {
        public static string Generate() {
            OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM InvalidVIN", Program.ConnectionString);
            DataTable dt = new DataTable();
            da.Fill(dt);

            string vin = String.Empty;
            do {
                vin = Gen();
            }
            while (dt.Select("SUBSTRING(VIN, 1, 6)=SUBSTRING('" + vin + "', 1, 6)").Length > 0);

            return vin;
        }

        private static string Gen() {
            // 第1位：生产国家代码
            // 1-美国，J-日本，S-英国，2-加拿大，K-韩国，T-瑞士，3-墨西哥，L-中国，V-法国，4-美国，R-台湾，W-德国，6-澳大利亚，Y-瑞典，9-巴西，Z-意大利 
            //string[] vin1 = { "1", "J", "S", "2", "K", "T", "3", "L", "V", "4", "R", "W", "6", "Y", "9", "Z" };

            // 第2位：汽车制造商代码
            // 1-Chevrolet，B-BMW，M-Hyundai，2-Pontiac，B-Dodge，M-Mitsubishi，3-Oldsmobile，C-Chrysler，M-Mercury，
            // 4-Buick，D-Mercedes，N-Infiniti，5-Pontiac，E-Eagle，N-Nissan，6-Cadillac，F-Ford，P-Plymouth，7－GM Canada，
            // G-General M，S-Subaru，8-Saturn G Suzuki，T-Lexus，8-Isuzu，H-Acura，T-Toyota，A-Alfa Romeo，H-Honda，
            // V-Volkswagen，A-Audi，J-Jeep，V-Volvo，A-Jaguar，L-Daewoo，Y-Mazda，L-Lincoln，Z-Ford，Z-Mazda，
            // G-所有属于通用汽车的品牌：Buick、Cadillac、Chevrolet、Oldsmobile, Pontiac、Saturn
            //string[] vin2 = { "1", "B", "M", "2", "B", "M", "3", "C", "M",
            //                  "4", "D", "N", "5", "E", "N", "6", "F", "P", "7",
            //                  "G", "S", "8", "T", "8", "H", "T", "A", "H",
            //                  "V", "A", "J", "V", "A", "L", "Y", "L", "Z", "Z",
            //                  "G"
            //                };

            // 第3-5位：汽车类型代码（不同的厂商有不同的解释) 
            // TRU/WAU-Audi，1YV/JM1-Mazda，4US/WBA/WBS-BMW，WDB-Mercedes Benz，2HM/KMH-Hyundai，VF3-Peugeot，
            // SAJ-Jaguar，WP0-Porsche，SAL-Land Rover，YK1/YS3-Saab，YV1-Volvo

            // 第1-3位：
            string[] vin1_3 = { "LSV", "LFV", "LDC", "LEN", "LHG", "LHB", "LKD", "LS5", "LSG" };//"LF" + (GetRandom().Next(2) == 0 ? "V" : "P"); 2011-7-17

            // 第4位：车身型式代码
            string[] vin4 = { "A", "B", "C", "E", "F", "H", "K" };

            // 第5位：发动机/变速器代码
            string[] vin5 = { "A", "B", "C", "E", "F", "G", "H", "J", "K", "L", "M" };

            // 第6位：乘员保护系统代码
            string[] vin6 = { "0", "1", "2", "3", "4", "5", "6" };

            // 第7-8位：车辆等级代码
            string[] vin7_8 = { "33", "9F", "9J", "5X" };

            // 第10位：年份代码（Y-2000，1-2001……A-2010，B-2011……）
            string[] vin10 = { 
                                 //"B", "C", "D", "E", "F", "G", "H", "J", "K", "L", 
                                 //"M", "N", "P", "R", "S", "T", "V", "W", "X", "Y",
                                 //"1", "2", "3", "4", "5", "6", "7", "8", "9", "A"
                                 "A", "B"
                             };

            // 第11位：装配厂代码
            string vin11 = "2"; // 上海大众

            // 第12-17位：车辆制造顺序号
            string vin12_17 = GetRandom().Next(1, 999999).ToString("000000");

            string vin =
                vin1_3[GetRandom().Next(vin1_3.Length)] +
                vin4[GetRandom().Next(vin4.Length)] +
                vin5[GetRandom().Next(vin5.Length)] +
                vin6[GetRandom().Next(vin6.Length)] +
                vin7_8[GetRandom().Next(vin7_8.Length)] +
                "$" +   // 第9位
                vin10[GetRandom().Next(vin10.Length)] +
                vin11 +
                vin12_17;

            return FillCheckBit(vin);
        }

        private static Random GetRandom() {
            long tick = DateTime.Now.Ticks;
            return new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32));
        }

        private static string FillCheckBit(string vin) {
            Dictionary<char, int> values = new Dictionary<char, int>();
            values.Add('0', 0);
            values.Add('1', 1);
            values.Add('2', 2);
            values.Add('3', 3);
            values.Add('4', 4);
            values.Add('5', 5);
            values.Add('6', 6);
            values.Add('7', 7);
            values.Add('8', 8);
            values.Add('9', 9);
            values.Add('A', 1);
            values.Add('B', 2);
            values.Add('C', 3);
            values.Add('D', 4);
            values.Add('E', 5);
            values.Add('F', 6);
            values.Add('G', 7);
            values.Add('H', 8);
            values.Add('J', 1);
            values.Add('K', 2);
            values.Add('L', 3);
            values.Add('M', 4);
            values.Add('N', 5);
            values.Add('P', 7);
            values.Add('R', 9);
            values.Add('S', 2);
            values.Add('T', 3);
            values.Add('U', 4);
            values.Add('V', 5);
            values.Add('W', 6);
            values.Add('X', 7);
            values.Add('Y', 8);
            values.Add('Z', 9);

            int[] powers = { 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 };

            int sum = 0;
            for (int i = 0; i < vin.Length; ++i) {
                if (vin[i] != '$') {
                    sum += values[vin[i]] * powers[i];
                }
            }

            int remainder = sum % 11;
            return vin.Replace("$", remainder == 10 ? "X" : remainder.ToString());
        }
    }
}
